<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <title>Enabling Logical Model Integration in the Eclipse Platform</title>
  <meta http-equiv="Content-Type"
 content="text/html; charset=iso-8859-1">
</head>
<body>
<h1>Enabling Logical Model Integration in the Eclipse Platform</h1>
<p>This document tries to capture the issues that are related to
integrating logical models into the Eclipse Platform. This is a
reiteration of what was captured <a href="logical-physical-public.html">here</a>
but tries to present the set of model characteristics of interest along
with related scenarios. The focus is not on defining a general API for
logical models. Instead, the focus is on identifying those points in
the Platform that degrade the user experience when working with logical
models and identifying possible solutions to these issues. The focus is
also on those issues that involve maintaining model consistency both
locally and remotely in a repository.</p>
<p>First we will describe some of the different model characteristics that we 
  have seen in various modeling tools built on top of Eclipse. Then we will describe 
  several scenarios and how they relate to these model characteristics. The scenarios 
  contain descriptions of what the ideal workflows could be without considering 
  the viability of making these a reality.</p>
<h2>Model Characteristics</h2>
<p>This section describes several different model characteristics that
are common in model tooling. This list is general and it is most likely
that real models will have a combination of these characteristics.</p>
<h3><a name="m1"></a>M.1 Model Element Maps to a Single File (One-to-One)</h3>
<p>The most straightforward relationship between model elements and file system 
  resources is a one-to-one mapping. That is, a model element maps directly to 
  a file system resources. An example of this is a Java class (or compilation 
  unit) which maps directly to the file that contains the class. </p>
<h3><a name="m2"></a>M.2 Multiple Model Elements in a Single File (Many-to-One)</h3>
<p>It is often the case that a single file will contain multiple model elements. 
  A simple example of this is a Java file that contains multiple compilation units 
  or classes. Usually, a file contains a single class but multiple classes in 
  the same file is supported. In this case, classes that appear in Java views 
  will still correspond to a single file but performing operations that are resource 
  based, such as repository operations, on the class will include all classes 
  contained in the file in the operation.</p>
<h3><a name="m3"></a>M.3 Model Contains Fixed Set of Files (Fixed Relationship)</h3>
<p>In some models, a model element may consist of a fixed set of files. We will 
  use an example from the Eclipse plug-in structure. When developing plug-ins, 
</p>
<ul>
  <li>a <em>plugin.xml</em> file is used to determine certain
characteristics of the plug-in</li>
  <li>a <em>plugin.properties</em> file is used to contain human
readable strings that appear in the plugin.xml. This is done to support
internationalization. Keys in the plugin.xml file reference entries in
the plugin.properties file.</li>
</ul>
<p>These two files are tied together in the sense that they are really
one entity that is stored in two files (in reality, there are other
files that are thus linked to the plugin.xml file but we'll only use
two files to keep it simple).</p>
<p>Another example of a fixed relationship is a Java package which consists of 
  all the direct file children of the package folder. That is, sub-folders of 
  the package folder (which model sub-packages) and the files that are contained 
  in those sub-folders are <span
 style="font-weight: bold;">not</span> part of the Java package.</p>
<h3><a name="m4"></a>M.4 Model Contains Variable Set of Files (Variable Relationship)</h3>
<p>In some tools, several files are related to a single model object
through a map file or interfile references. For a simple case, consider</p>
<ul>
  <li><em>A.map</em>: a map file that identifies (i.e. contains
references to) the files which make up a model element</li>
  <li><em>AClass.java</em>: a java file contained in the model element</li>
  <li><em>APage.jsp</em>: a JSP contained in the model element</li>
  <li>potentially additional files referenced from the map file</li>
</ul>
<p>An additional restriction may be that the names of some or all of
the files have a common string in the file name (e.g. <em>A</em>).</p>

<h3><a name="m5"></a>M.5 Model Contains Strong References</h3>
<p> In some cases, it is possible to have a model that doesn't necessarily contain 
  certain files but cannot be reasonably rendered without them. An example of 
  this is a diagram that described the relationship between a set a Java classes. 
  The diagram will contain layout information and perhaps even some class relationship 
  information but will not likely duplicate information found in the classes themselves, 
  such as method signatures. If one or more of the classes in the diagram were 
  not available, it may not be possible to render portions of the diagram.</p>

<h3><a name="m6"></a>M.6 Multi-File Model is Atomic</h3>
<p> In some cases, a model may be persisted in several file system resources where 
  each file is meaningless on its own. An example would be a large diagram that 
  is divided into files but cannot be rendered if one of the files is missing. 
  This is similar to the fixed or variable relationship cases but has the added 
  characteristic that operations should never be performed on the file-system 
  resources individually. </p>
<h3><a name="m7"></a>M.7 Layered Models</h3>
<p>It is often the case that there are many model layers involved in a product. 
  Consider this layering:</p>
<ol>
  <li>Platform resource model</li>
  <li>Java model</li>
  <li>J2EE</li>
  <li>WSDL</li>
</ol>
<p>Each of these models is built on top of the lower layer (i.e. layer 2 is built 
  on top of layer 1, etc.). It is also true that the higher layers may be built 
  on top of several lower level model layers. We commonly refer to the mapping 
  of model elements to files as <em>logical-to-physical</em> mapping. We will 
  refer to mapping from one logical model to another as <em>logical-to-logical</em> 
  mapping.</p>

<h3><a name="m8"></a>M.8 Model Not Contained In Files</h3>
<p> It is worth mentioning the case where a model is not persisted in local files 
  but is instead persisted in some other location (e.g. a database). Some of the 
  scenarios that will be mentioned below are still relevant to this case (e.g. 
  problem reporting).</p>

<h2>Scenarios for Maintaining Model Consistency</h2>
<p>This section covers various scenarios, work flows or use cases that can potentially 
  have an effect on the consistency of a model. There are basically two methods 
  of maintaining model consistency:</p>
<ul>
  <li>Ensure that operations performed on model elements do so in a manner that 
    preserves model consistency. This applies to both local operations (file content 
    modification, delete, rename, etc.) and remote operations (check-out, check-in, 
    update, tag as version, etc.).</li>
  <li>Report any model inconsistencies to the user. Ideally, this should be done 
    in such a way as to point towards a solution. This could be done by linking 
    problems to editors or even providing QuickFixes for fixing the problem.</li>
</ul>
<p>Ensuring that all the operations performed on a model will maintain
model consistency is fairly straight forward when operations are
launched from the tooling associated with the model in question.
However, it is often the case that operations are performed on the
elements of lower level models directly. For instance, a user who edits
the <em>plugin.properties</em> file directly may remove an entry that
is still referenced by the <em>plugin.xml</em> file. Or, in the
layered model case, a user may delete a Java file that is contained in
a model element of a higher level model. These types of changes lead to
a greater chance of models becoming inconsistent.</p>
<p>The work flows in the section are related back to the model characteristics 
  described previously with descriptions of what currently occurs as well as what 
  would be the desirable behavior. The statement of the desirable behavior is 
  by no means a statement of the viability of such a solution. It is only something 
  to shoot for.</p>
<h3><a name="s1"></a>S.1 Problem Reporting</h3>
<p>Currently in Eclipse, dealing with model inconsistencies is mainly
done using problem reporting. However, the mechanisms provided by
Eclipse (build, markers, Problems view) are highly file system centric.
This makes the reporting of problems difficult as they are always
associated with file system resources. This has several shortcomings:</p>
<ul>
  <li>The relationship between a model and the underlying file system representation 
    may not be obvious to the user. </li>
  <li>It is often the case that multiple problem markers are associated with a 
    single problem. In the current Problems view, there is no mechanism for displaying 
    this type of relationship to the user.</li>
</ul>
<p>Ideally, the Problems view should display problems that are associated with 
  any model element, whether it be a file-system resource or an element of a higher 
  level model. Furthermore, the ability to group related problems together using 
  a tree view or some other type of grouping mechanism would be helpful when the 
  user is presented with a lot of problems that are really all symptoms of one 
  larger problem.</p>
<p>The following sub-sections present specific problem reporting scenarios.</p>
<h4>Parse Errors</h4>
<p>Consider the case where a model element is persisted in at least one file which 
  is XML. If that file cannot be parsed, the XML parser will create a problem 
  marker that contains a description of the parse error. Here are some scenarios 
  related to this type of problem:</p>
<ul>
  <li>In the many-to-one case (<a href="#m2">M.2</a>), the file may contain several 
    logical model elements, none of which can be recognized by the model tooling 
    due to the parse error. In this case, there may be no logical model element 
    to associate the error with. However, the model tooling may still which to 
    either annotate the problem representing the parse error with a more understandable 
    description or associate another problem with the file and have it wrap or 
    in some other way override the lower level problem. That's not to say that 
    the lower level problem would be entirely hidden from the user but instead 
    that it would be somehow grouped with the higher-level problem description. 
    This problem could also occur in the one-to-one or one-to-many cases if the 
    parse error prevented the model element from being recognized by the model 
    tooling.</li>
  <li>In the one-to-many cases (<a href="#m3">M.3</a>, <a href="#m4">M.4</a>, 
    <a href="#m5">M.5</a>, <a href="#m6">M.6</a>), it is possible that the contents 
    of the unparsable file only constitute part of a model element. In this case, 
    the model tooling may wish to associate a problem with this logical model 
    element. The following should be considered: 
    <ul>
      <li>The logical model element may or may not map to a file system resource. 
        In either case, it should be possible to have a problem appear in the 
        Problems view that is associated with the model element and contain a 
        description that makes sense in the model space.</li>
      <li>The problem associated with the logical element should take precedence 
        over the lower level problem. Again, it could either override or parent 
        the lower level problem.</li>
    </ul>
  </li>
</ul>
<h4>Stale References</h4>
<p>Another case to consider is when model elements contain references to other 
  model elements (<a href="#m4">M.4</a>, <a href="#m5">M.5</a>). Changes to a 
  model element may cause references to become stale. That is, a referenced element 
  could be removed or modified in such a way as to make any references to the 
  element no longer valid. With the current Problems view, a problem could be 
  associated with the location in the file where the reference appears. If the 
  stale reference appears multiple times, then multiple markers could be created. 
  However, providing a link to the position in the file where the link appears 
  may not be enough to help the user to decide how to fix the problem. Also, the 
  user would need to fix the problem in each location it appeared. </p>
<p>Ideally, a single problem item should identify the existence of the stale reference. 
  This would allow the user to see the single cause of the multiple stale references. 
  It may still be desirable to associate problems with each of the elements that 
  contain stale references and also with each particular occurrence of a stale 
  reference but the user should only need to see the specific locations if they 
  decided to deal with each occurrence individually.</p>
<h4>Problems in Logical Models that Don't Map to Files</h4>
<p>Models that are not persisted in files (<a href="#m8">M.8</a>) may still have 
  model consistencies problem that should appear in the problems view. Currently, 
  problems cannot be associated with logical model elements that do not have a 
  corresponding resource unless the model tooling has it's own problems view. 
  Having multiple views that serve the same purpose is confusing for users.</p>
<h4>Filtering Problems By Selection</h4>
<p>The Problems view currently has the ability to filter by selection. This only 
  works when the items in the selection have a one-to-one mapping to file system 
  resources. Ideally, the following would be supported:</p>
<ul>
  <li>Support one-to-many mappings (all problems associated with any resource 
    in the mapping should be shown).</li>
  <li>Support many-to-one mappings (i.e. only those problem associated with a 
    portion of the file would be shown).</li>
  <li>Support logical element containment filter (i.e. if a logical model element 
    is selected, show any problems that reference that model element).</li>
  <li>Support logical-to-logical mappings (i.e. if a logical model element at 
    a higher level is selected, display problems for lower levels model elements 
    contained by the higher level element).</li>
</ul>
<p>With this support, the user could select any element in the UI and see what 
  problems existed for that element.</p>
<h4>Model Layering</h4>
<p>Many of the scenarios presented previously involve layered models. However, 
  it is worthwhile to mention specific instances of how model layering affects 
  problem reporting. The user will often work at a particular model level and 
  will therefore like to see problems stated in such a way that is consistent 
  with that layer. Thus is would be desirable to be able to:</p>
<ul>
  <li>arrange problems by model layer: i.e. group problems associated with lower 
    level problems as children of a problem entry associated with the model layer 
    at which the user is working.</li>
  <li>filter problems by model layer: i.e. hide errors of lower level models unless 
    the model level at which the user is working explicitly includes problems 
    from the lower layer.</li>
</ul>
<h3><a name="s2"></a>S.2 Operation Participation</h3>
<p>In this section we look at various operations and their effect on model consistency.</p>
<h4>File Rename and Deletion</h4>
<p>First, lets look at what happens when a file that is part of a model element 
  is renamed. The following conditions will result in model inconsistencies that 
  need to be corrected.</p>
<ul>
  <li>The file may be referenced by a model element. This can happen in cases 
    <a href="#m4">M.4</a> and <a href="#m5">M.5</a></li>
  <li>Other files may have a name that is linked to the name of the file as described 
    in <a href="#m4">M.4</a></li>
  <li>The file is part of a fixed relationship as in <a href="#m3">M.3</a> or 
    is part of a model whose files should not be modified individually as in M.6.</li>
</ul>
<p>The currently supported solution for all these cases is for a builder to recognize 
  the inconsistency and place a problem marker on an appropriate file. The model 
  tooling could associate a QuickFix with the problem that would allow the user 
  to correct the problem in a single operation (as opposed to renaming all the 
  necessary files one-by-one) but that is the best they could do. </p>
<p>Ideally, the model tooling would want some or all of these abilities:</p>
<ul>
  <li>The ability to augment the current operation with additional modifications. 
    For instance, any references could be updated and linked files renamed in 
    the same operation as the original file rename.</li>
  <li>The ability to describe the augmentation that will take place to the user 
    as part of the UI of the original operation. The user will want to know of 
    any additional modifications that will take place, as well as any conditions 
    that will result in model inconsistency (i.e. the model tooling may not be 
    able to determine the proper augmentation that will preserve model integrity).</li>
  <li>The ability to prevent the rename in the case where the model will be compromised 
    in such a way that recovery is not possible.</li>
</ul>
<p>File deletion is similar to the rename case with some additional considerations:</p>
<ul>
  <li>Deleting a file may have a larger impact on containing model elements. For 
    example, for a diagram, removing a class may also invalidate several relationships 
    in the diagram. It may be desirable to make the user aware of the repercussions 
    before performing the delete.</li>
  <li>Deleting a file that is an important part of a model element, as in <a href="#m6">M.6</a>, 
    could offer to delete the containing model element.</li>
</ul>
<h4>Folder Rename or Deletion</h4>
<p>The effects on model consistency are harder to determine on folder (or project) 
  deletion, simply because there are potentially many files being renamed or deleted. 
  It is possible that many file references may become stale upon folder deletion 
  but it is just as likely that all the files contained in or referenced by the 
  model were all contained in the same folder so deleting that folder may introduce 
  no inconsistencies.</p>
<h4>Content Modification</h4>
<p>There are two cases of interest when looking at file content modification.</p>
<ul>
  <li>A model may be made up of multiple files that should never be modified directly 
    (as in case <a href="#m6">M.6</a>). In this case, any external modifications 
    should be prevented (or, at least, strongly discouraged).</li>
  <li>File contents can be modified directly but may contain references embedded 
    by higher level model tooling. An example of this could be Java annotations 
    that are used by a diagram. Removing an annotation may have an adverse affect 
    on the diagram. The user should be made aware of what may occur.</li>
</ul>
<h4>The Effects of Model Layering</h4>
<p>For operation participation, the following list of issues arise when model 
  layering is considered:</p>
<ul>
  <li>Each model layer may have it's own set of operations that could potentially 
    be participated in. For instance, a Java rename is different from a Resource 
    Navigator rename. Higher level models would need to be able to participate 
    in any operations of lower level models that may affect their model consistency. 
    For instance, for a file rename, model tooling that is build on top of Java 
    would want to participate in both the Java and Platform Resource rename operations.</li>
  <li>Operations of higher levels may make use of those from lower levels. However, 
    the model tooling would only want to participate at one level (the highest 
    possible). A mechanism to disable participation at lower levels when higher 
    level participation takes place would be needed.</li>
  <li>In those cases where participation at a higher level is not possible, the 
    model tooling may still want to participate at the lowest level (i.e. file 
    content modification, rename or delete). The types of operation augmentation 
    that occur at this level may be reduced due to the lack of knowledge of the 
    overall context of the operation, but the model may still wish to notify the 
    user of any model inconsistencies that are introduced.</li>
  <li>Multiple models may be participating in a particular operation and may each 
    augment the operation with additional modification. A further complication 
    is that some may participate at higher levels while others may only participate 
    at lower levels.</li>
</ul>
<p>Some things to consider here are:</p>
<ul>
  <li>One crucial aspect of any such participation mechanism is that it does not 
    have a significant performance impact. This is especially important if participation 
    at the lowest levels is supported as this path will be hit by most, if not 
    all, tools built on top of Eclipse. 
    <ul>
      <li>Another aspect of performance is plug-in loading. Operations on lower 
        level models may be performed before the plug-ins of the higher level 
        models are even loaded. Declarative filtering may be needed to efficiently 
        prune the list of interested participants.</li>
    </ul>
  </li>
  <li>There are a set of standard operations (create, delete, move and rename) 
    that apply across models. Operation participation would be simplified if these 
    standard operations were defined by the platform in some form.</li>
</ul>
<p>It is also interesting to note that Java refactorings support certain types 
  of participation (create, delete, move and rename).</p>
<h4>Working with Editors</h4>
<p>Although not technically a model consistency issue, opening an editor is similar 
  to performing other operations. Here are a few cases involving logical models 
  that impact the opening of editors.</p>
<ul>
  <li>Each resource and/or element usually has a default editor associated with 
    it. For instance, clicking on a Java file will open a Java editor on that 
    file. However, if this file is part of a higher level model and is actually 
    generated by that model (case <a href="#m6">M.6</a>), the model tooling may 
    not want the user to edit the file directly. In this case, it may be more 
    appropriate for the default editor for such a Java file to be the editor of 
    the model used to generate the file.</li>
  <li>Eclipse strives to have only one editor open on a particular resource, be 
    it a file system resource or a logical model element. Hence, opening an editor 
    on an element searches through the open editors to find a match before opening 
    a new one. 
    <ul>
      <li>For model elements that contain one or more resources, this means that 
        opening up an editor on a file contained in the model element should match 
        an open editor on that model element.</li>
      <li>In the case where a file may contain multiple editable model elements, 
        the user would not necessarily want the file to match with open editors 
        on the file sub-elements.</li>
    </ul>
  </li>
  <li>Problems are linked to a location (i.e. line number) is a file. Eclipse 
    provides the capability of opening and editor on the problem and showing the 
    location of the problem. This is straightforward if the mapping from model 
    element to resource is one-to-one but has some complications in other cases: 
    <ul>
      <li>If the editor that is opened is on a model element that contains multiple 
        files, some means of translating the file location to the appropriate 
        Area of the editor is needed. As an example, consider the plug-in model 
        in <a href="#m3">M.3</a>. A problem marker on a key in the plugin.properties 
        file should not only open the plug-in manifest editor but show the page 
        that deals with the NLS keys and highlight the offending key.</li>
      <li>If the file contains multiple editable model elements, a means of opening 
        an editor on the appropriate model element is needed. This is less of 
        an issue if problems can be associated directly with model elements.</li>
    </ul>
  </li>
</ul>
<h3><a name="s4"></a>S.3 Working with Repositories</h3>
<p>When working with logical models, the user would like to be able to select 
  logical model elements that appear in Eclipse and perform repository operations 
  on them. However, repository tooling tends to be file based so a conversion 
  from the model space to the file system resource space is required. We have 
  introduced <a href="logical-physical-mappings.html">API in 3.1 M5</a> that supports 
  the mapping of logical elements to their underlying file system resources. As 
  of 3.1 M5, the following is support:</p>
<ul>
  <li>Model elements with one-to-one mappings to resources have always
been supported.</li>
  <li>Model elements with one-to-many mappings, can now be the input to
repository operations.
    <ul>
      <li>Fixed relationships are the easiest as the remote state of
the model is not required</li>
      <li>For variable relationships, additional API is specified to
allow the model to query the remote state in order to determine if
there are additional resources in the remote copy of the model.</li>
    </ul>
  </li>
  <li>Model elements with many model elements in a single file can still be input 
    to a repository operation. However, the set of model elements being affected 
    may be greater than the set the operation was performed on. For instance, 
    if a *.java files contains multiple classes, performing a repository operation 
    on any of the contained classes will perform the operation on all the contained 
    classes. </li>
</ul>
<p>The following sections highlight issues that still exist.</p>
<h4>Model Participation in Repository Operations</h4>
<p>There are some cases where a model may want to participate in repository operations 
  for the purpose of augmenting the list of model elements or file system resources 
  that are being operated on. Examples of when this may be necessary are:</p>
<ul>
  <li>If a repository operation is performed on a single model element that is 
    contained in the same file with other model elements (case <a href="#m2">M.2</a>), 
    the user will need to be made aware of the additional model elements that 
    will be included in the operation.</li>
  <li>If the file being operated on is part of a model that should be treated 
    as an atomic unit (case <a href="#m6">M.6</a>), then any operations on the 
    file itself should instead be performed on the entire model.</li>
  <li>If multiple model layers are involved, repository operations on elements 
    in lower layers may have a corrupting affect if the higher layers are not 
    involved. Some means of making the user aware of this and potentially including 
    additional resources in the operation may be helpful.</li>
</ul>
<p>The repository tooling may also need to obtain additional input from the user. 
  Although the operation is being performed on file system resources, the relationship 
  between the resources and the originating model should be made obvious to the 
  user.</p>
<h4>Model Participation in Merging</h4>
<p>One of the more complicated scenarios involving repository operations is that 
  of merging remote changes with local changes. Eclipse has API which supports 
  model based merging for the one-to-one case (<a href="#m1">M.1</a>). This API 
  could also be used to handle the many-to-one case (<a href="#m2">M.2</a>). However, 
  there is currently no mechanism for performing an atomic merge on a model element 
  that contains multiple files. What would be required in this case is API between 
  the model tooling and repository provider in order to reconcile the logical 
  model to the physical model when performing repository operations such as merging. 
</p>
<p>One potential complication is that a merge operation may involve model elements 
  form different model layers or from different model tooling. Either there would 
  need to be a single merge mechanisms that was capable of performing merges on 
  multiple models simultaneously or the merges would need to be sequences. The 
  former case is more desirable than the later from a usability standpoint.</p>
<h4>Decorations</h4>
<p>Decorating elements that appear in the UI with their state relative to the 
  repository provides valuable feedback to the user in some cases. One such case 
  is a dirty decorator that, when present, indicates that the element has changed 
  locally since the time it was loaded from the repository. </p>
<ul>
  <li>For the one-to-one and one-to-many case, showing the dirty decoration is 
    straightforward in the sense that the element is dirty if any of it's contained 
    files are dirty. </li>
  <li>For the many-to-one, if the file is dirty, it is impossible to determine 
    which particular element is dirty without the ability to compare the new file 
    contents with the contents in the repository. Fetching the contents from the 
    repository is not something that should be done when calculating decorations.</li>
</ul>
<h4>Bootstrapping</h4>
<p>A related issue is that of bootstrapping. In other words, how does a
user load model elements that were created by other users. To do this,
a root access point is required. In Eclipse, the project acts as this
root. Therefore, the user must first load a project and can then access
the model elements it contains. In the cases where models span
projects, Team projects sets can be used to bootstrap a workspace.</p>
<p>There are a couple of issues involving the use of project sets in
this way:</p>
<ul>
  <li>Project set creation is separate from repository operations. This means 
    that the user that shares a model must also remember to create a project set. 
    If the model spans projects, they must understand which projects are to be 
    included. </li>
  <li>Projects sets are just files. If projects are added to or removed from a 
    project set, the project set file must be regenerated and redistributed.</li>
  <li>A project set just contains a set of projects. There is no statement of 
    relationships between other project sets.</li>
</ul>
<p>One simple means of addressing this may be to support the grouping projects 
  together in a way that ensured that if one got loaded from a repository, they 
  all got loaded.</p>
<h2>Summary</h2>
<p>The required support for the scenarios presented in this document can be broken 
  down into three separate features:</p>
<ol>
  <li>Generic views</li>
  <ul>
    <li>the main view of interest for model consistency issues is the Problems 
      view </li>
  </ul>
  <li>Repository operations available on logical models</li>
  <ul>
    <li>repository provider operations available on model elements that
appear in the UI</li>
    <li>while performing an operation, repository provider should show
information in a form consistent with the originating model</li>
  </ul>
  <li>Operation Participation 
    <ul>
      <li>The ability for model tooling to participate in the
operations of lower level models (e.g. Java or the Platform resource
model) in order to ensure model consistency</li>
    </ul>
  </li>
</ol>
<p>Although there is some overlap between these features, they can each be addressed 
  as separate issues.</p>
</body>
</html>
